package com.onesports.intelligent.k12.polarlight.service.sys;

import cn.binarywang.wx.miniapp.api.WxMaMsgService;
import cn.binarywang.wx.miniapp.api.WxMaService;
import cn.binarywang.wx.miniapp.bean.WxMaTemplateData;
import cn.binarywang.wx.miniapp.bean.WxMaUniformMessage;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.onesports.framework.kit.common.util.ParamUtils;
import com.onesports.framework.kit.common.util.TimeUtils;
import com.onesports.intelligent.k12.polarlight.annotation.DistributedLock;
import com.onesports.intelligent.k12.polarlight.common.utils.DateUtils;
import com.onesports.intelligent.k12.polarlight.config.ApplicationProperties;
import com.onesports.intelligent.k12.polarlight.constant.LockConstants;
import com.onesports.intelligent.k12.polarlight.constant.MessageTemplatePageConstants;
import com.onesports.intelligent.k12.polarlight.domain.entity.course.ClassInfo;
import com.onesports.intelligent.k12.polarlight.domain.entity.course.CourseScheduleDetail;
import com.onesports.intelligent.k12.polarlight.domain.entity.market.Message;
import com.onesports.intelligent.k12.polarlight.domain.entity.market.MessageNotify;
import com.onesports.intelligent.k12.polarlight.domain.entity.organization.Coach;
import com.onesports.intelligent.k12.polarlight.domain.entity.organization.OrganizationStaff;
import com.onesports.intelligent.k12.polarlight.domain.entity.student.Student;
import com.onesports.intelligent.k12.polarlight.domain.entity.student.UserStudentRel;
import com.onesports.intelligent.k12.polarlight.domain.entity.sys.Config;
import com.onesports.intelligent.k12.polarlight.domain.entity.sys.WxMessageLog;
import com.onesports.intelligent.k12.polarlight.domain.entity.sys.WxUser;
import com.onesports.intelligent.k12.polarlight.domain.vo.message.CourseMessageContentVO;
import com.onesports.intelligent.k12.polarlight.domain.vo.order.AutoPayVO;
import com.onesports.intelligent.k12.polarlight.enums.MessageTypeEnum;
import com.onesports.intelligent.k12.polarlight.enums.SysConfigTypeEnum;
import com.onesports.intelligent.k12.polarlight.mapper.course.ClassInfoMapper;
import com.onesports.intelligent.k12.polarlight.mapper.course.CourseMapper;
import com.onesports.intelligent.k12.polarlight.mapper.course.CourseScheduleDetailMapper;
import com.onesports.intelligent.k12.polarlight.mapper.market.MessageMapper;
import com.onesports.intelligent.k12.polarlight.mapper.market.MessageNotifyMapper;
import com.onesports.intelligent.k12.polarlight.mapper.market.OrdersMapper;
import com.onesports.intelligent.k12.polarlight.mapper.organization.CoachMapper;
import com.onesports.intelligent.k12.polarlight.mapper.organization.OrganizationStaffMapper;
import com.onesports.intelligent.k12.polarlight.mapper.student.StudentMapper;
import com.onesports.intelligent.k12.polarlight.mapper.student.UserStudentRelMapper;
import com.onesports.intelligent.k12.polarlight.mapper.sys.ConfigMapper;
import com.onesports.intelligent.k12.polarlight.mapper.sys.WxMessageLogMapper;
import com.onesports.intelligent.k12.polarlight.mapper.sys.WxUserMapper;
import com.onesports.intelligent.k12.polarlight.util.RedisUtils;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import me.chanjar.weixin.common.error.WxErrorException;
import org.apache.commons.compress.utils.Lists;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.thymeleaf.util.StringUtils;

import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.stream.Collectors;

/**
 * function：消息通知服务类
 *
 * @author wangcx
 * @since 2022/7/18 9:56
 */
@Service
@RequiredArgsConstructor
@Slf4j
public class MessageNotifyService extends ServiceImpl<MessageNotifyMapper, MessageNotify> {


    private final CourseMapper courseMapper;
    private final ConfigMapper configMapper;
    private final MessageMapper messageMapper;
    private final WxMessageLogMapper wxMessageLogMapper;
    private final WxMaService wxMaService;
    private final ApplicationProperties properties;
    private final CoachMapper coachMapper;
    private final StudentMapper studentMapper;
    private final WxUserMapper wxUserMapper;
    private final UserStudentRelMapper userStudentRelMapper;
    private final OrdersMapper ordersMapper;
    private final CourseScheduleDetailMapper courseScheduleDetailMapper;
    private final ClassInfoMapper classInfoMapper;
    private final OrganizationStaffMapper organizationStaffMapper;
    private final RedisUtils redisUtils;


    /**
     * function：发送上课提醒
     *
     * @author wangcx
     * @since 2022/7/25 9:44
     */
    @DistributedLock(value = LockConstants.CLASS_REMIND)
    public void classRemindNotification() {
        String key = "REMIND";
        if (redisUtils.exists(key)) {
            return;
        }
        redisUtils.set(key, key, 30L);
        Date today = new Date();
        //提前N小时家长通知
        Integer parentHours = this.getConfigValue(SysConfigTypeEnum.G);
        Integer coachHours = this.getConfigValue(SysConfigTypeEnum.F);
        List<WxUser> parentWxUsers = Lists.newArrayList();
        WxUser coachWxUser = new WxUser();
        List<CourseMessageContentVO> parentCourseList = Lists.newArrayList();
        List<CourseMessageContentVO> coachCourseList = Lists.newArrayList();
        if (Objects.nonNull(parentHours)) {
            Date parentDate = DateUtils.addHours(today, parentHours);
            parentCourseList = courseMapper.getCourseMessageContent(
                    DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD_HH_MM, parentDate));
        }
        if (Objects.nonNull(coachHours)) {
            Date coachDate = DateUtils.addHours(today, coachHours);
            coachCourseList = courseMapper.getCourseMessageContent(
                    DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD_HH_MM, coachDate));
        }
        if (CollectionUtils.isNotEmpty(parentCourseList)) {
            //家长推送
            for (CourseMessageContentVO i : parentCourseList) {
                // 根据班级id获取家长的wxUser集合
                parentWxUsers = this.classInfoMapper.getParentWxUsers(i.getClassInfoId());
                if (CollectionUtils.isNotEmpty(parentWxUsers)) {
                    if (CollectionUtils.isNotEmpty(parentWxUsers)) {
                        parentWxUsers.forEach(x -> {
                            // 公众号消息推送
                            this.remindCoachAndParent(x, i);
                        });
                    }
                }
            }
        }
        if (CollectionUtils.isNotEmpty(coachCourseList)) {
            //教练推送
            for (CourseMessageContentVO i : coachCourseList) {
                coachWxUser = coachMapper.getWxUserByCoachId(i.getCoachId());
                if (ParamUtils.isNotEmpty(coachWxUser)) {
                    if (!parentWxUsers.contains(coachWxUser) && ParamUtils.isNotEmpty(coachWxUser.getOpenId())) {
                        // 公众号消息推送
                        this.remindCoachAndParent(coachWxUser, i);
                    }
                }
            }
        }
    }

    /**
     * function: 集合推送家长和教练通知
     *
     * @param wxUser WxUser
     * @param vo     添加message所需字段vo
     * @author WangCX
     * @since 2022/8/11 17:58
     */
    @Transactional(rollbackFor = Exception.class)
    public void remindCoachAndParent(WxUser wxUser, CourseMessageContentVO vo) {
        List<WxMaTemplateData> dataList = new ArrayList<>();
        // 上课时间
        String classTime = new SimpleDateFormat("yyyy-MM-dd").format(vo.getCourseDate()) + " "
                + DateUtils.dateToWeek(vo.getCourseDate()) + " "
                + new SimpleDateFormat("HH:mm").format(vo.getStartTime()) + "-"
                + new SimpleDateFormat("HH:mm").format(vo.getEndTime());
        dataList.add(new WxMaTemplateData("first", "您有课程即将开始，请提前做好准备。"));
        dataList.add(new WxMaTemplateData("keyword1", vo.getCourseName()));
        dataList.add(new WxMaTemplateData("keyword2", classTime));
        String content = "您于 " + classTime + "有“" + vo.getCourseName() + "”，请提前做好课前准备";
        Message message = new Message();
        message.setContent(content);
        message.setMsgType(MessageTypeEnum.COURSE_REMIND.getValue());
        message.setTitle(MessageTypeEnum.COURSE_REMIND.getDesc());
        message.setReceiverType(MessageTypeEnum.RECEIVER_TYPE_OTHER.getValue());
        this.messageMapper.insert(message);
        MessageNotify notify = new MessageNotify();
        notify.setMessageId(message.getId());
        notify.setSendTime(new Date());
        this.save(notify);
        if (ParamUtils.isNotEmpty(wxUser)) {
            // 公众号消息推送
            publicPush(dataList, null, wxUser, properties.getWx().getMessageTemplate().getCourseRemind(), content);
            log.info("消息通知-上课提醒：" + "\n" + "微信主键id：" + wxUser.getId() + " 班级id:" + vo.getClassInfoId());
        }

    }

    /**
     * function：自动扣款通知
     *
     * @param orderId 订单Id
     * @author wangcx
     * @since 2022/7/21 9:46
     */
    @Transactional(rollbackFor = Exception.class)
    public void autoPayRemind(String orderId) {
        // 获取订单详情
        AutoPayVO payVO = ordersMapper.getPayVo(orderId);
        // 消息内容
        if (ParamUtils.isEmpty(payVO.getCourseDate())) {
            return;
        }
        String content = "您的学员：" + payVO.getStudentName() +
                "的商品：" + payVO.getProductName() + " 开课时间：" + TimeUtils.toText(payVO.getCourseDate()) + " "
                + DateUtils.dateToWeek(payVO.getCourseDate()) + " " + new SimpleDateFormat("HH:mm").format(payVO.getStartTime())
                + "自动扣款" + payVO.getActuallyAmount() + "成功。";

        List<WxMaTemplateData> dataList = new ArrayList<>();
        // 时间
        String time = new SimpleDateFormat("yyyy-MM-dd HH:mm").format(new Date());
        // 微信通用消息模板
        dataList.add(new WxMaTemplateData("first", "您的课程(订单" + payVO.getOrderNo() + ")已自动扣款成功"));
        dataList.add(new WxMaTemplateData("keyword1", payVO.getProductName()));
        dataList.add(new WxMaTemplateData("keyword2", "课款缴费"));
        dataList.add(new WxMaTemplateData("keyword3", payVO.getActuallyAmount() + "元"));
        dataList.add(new WxMaTemplateData("keyword4", time));
        dataList.add(new WxMaTemplateData("keyword5", payVO.getStudentName()));

        // 存入消息表和消息通知表
        Message message = new Message();
        message.setContent(content);
        message.setMsgType(MessageTypeEnum.AUTO_PAY_REMIND.getValue());
        message.setTitle(MessageTypeEnum.AUTO_PAY_REMIND.getDesc());
        message.setReceiverType(MessageTypeEnum.RECEIVER_TYPE_OTHER.getValue());
        this.messageMapper.insert(message);
        MessageNotify notify = new MessageNotify();
        notify.setMessageId(message.getId());
        notify.setSendTime(new Date());
        this.save(notify);
        WxUser wxUser = getWxUserByStuId(payVO.getStudentId());
        if (ParamUtils.isNotEmpty(wxUser) && ParamUtils.isNotEmpty(wxUser.getOpenId())) {
            // 公众号消息推送
            publicPush(dataList, MessageTemplatePageConstants.MY_ORDER, wxUser,
                    properties.getWx().getMessageTemplate().getAutoPay(), content);
            log.info("消息通知-自动扣款通知：" + content);
        }

    }

    /**
     * function：课款不足提醒
     *
     * @param patriarchWxUserId 父母WxUserId
     * @param coachId           教练Id
     * @param studentIds        学生id集合
     * @param scheduleDetailId  课表详情id
     * @param courseId          课程id
     * @author wangcx
     * @since 2022/7/22 15:47
     */
    @Transactional(rollbackFor = Exception.class)
    public void noEnoughMoney(String patriarchWxUserId, String coachId, List<String> studentIds, String scheduleDetailId, String courseId) {
        // 根据课表id获取开始和结束时间 和日期
        CourseScheduleDetail courseScheduleDetail = courseScheduleDetailMapper.selectById(scheduleDetailId);
        // 获取学员姓名
        List<String> studentNames = this.studentMapper.selectList(new LambdaQueryWrapper<Student>().in(Student::getId, studentIds))
                .stream().map(Student::getStudentName).collect(Collectors.toList());
        String names = StringUtils.join(studentNames, "、");
        // 课程名称
        String courseName = this.courseMapper.selectById(courseId).getCourseName();
        // 时间
        String time = new SimpleDateFormat("yyyy-MM-dd").format(courseScheduleDetail.getCourseDate()) + " "
                + new SimpleDateFormat("HH:mm").format(courseScheduleDetail.getStartTime())
                + "-" + new SimpleDateFormat("HH:mm").format(courseScheduleDetail.getEndTime());
        // 消息内容
        String content = courseName + "，于" + time + "的课程由于学员(" + names
                + ")课款不足，本节课无法开课。";
        // 微信通用消息模板
        List<WxMaTemplateData> dataList = new ArrayList<>();
        dataList.add(new WxMaTemplateData("first", "Hi~您报名的课程课款不足，请及时充值！" + "\n时间：" + time));
        dataList.add(new WxMaTemplateData("keyword1", courseName));
        dataList.add(new WxMaTemplateData("keyword2", names));

        // 存入消息表和消息通知表
        Message message = new Message();
        message.setContent(content);
        message.setMsgType(MessageTypeEnum.STUDENT_NO_ENOUGH.getValue());
        message.setTitle(MessageTypeEnum.STUDENT_NO_ENOUGH.getDesc());
        message.setReceiverType(MessageTypeEnum.RECEIVER_TYPE_ORG.getValue());
        this.messageMapper.insert(message);
        MessageNotify notify = new MessageNotify();
        notify.setMessageId(message.getId());
        notify.setSendTime(new Date());

        // 给家长发送消息
        WxUser patriarchWxUser = this.wxUserMapper.selectById(patriarchWxUserId);
        // 公众号消息推送
        if (ParamUtils.isNotEmpty(patriarchWxUser) && ParamUtils.isNotEmpty(patriarchWxUser.getOpenId())) {
            publicPush(dataList, MessageTemplatePageConstants.MY_MONEY, patriarchWxUser,
                    properties.getWx().getMessageTemplate().getNoEnoughMoney(), content);
            log.info("消息通知-课款不足提醒：家长" + content);
        }
        notify.setOrganizationStaffId(getOrgStaffIdByOrgId(courseScheduleDetail.getOrganizationId()));


        // 给教练发送消息
        String coachWxUserId = this.coachMapper.selectOne(new LambdaQueryWrapper<Coach>()
                .eq(Coach::getId, coachId)).getWxUserId();
        WxUser coachWxUser = this.wxUserMapper.selectById(coachWxUserId);
        // 微信通用消息模板
        List<WxMaTemplateData> dataList2 = new ArrayList<>();
        dataList2.add(new WxMaTemplateData("first", "Hi~您的学员课款不足，请提醒他及时充值！" + "\n时间：" + time));
        dataList2.add(new WxMaTemplateData("keyword1", courseName));
        dataList2.add(new WxMaTemplateData("keyword2", names));
        // 公众号消息推送
        if (ParamUtils.isNotEmpty(coachWxUser) && ParamUtils.isNotEmpty(coachWxUser.getOpenId())) {
            publicPush(dataList2, null, coachWxUser, properties.getWx().getMessageTemplate().getNoEnoughMoney(), content);
            log.info("消息通知-课款不足提醒：教练 " + content);
        }

        this.save(notify);

    }

    /**
     * function: 通知家长和教练当前班级未满足开课要求
     *
     * @param scheduleDetailId  课表详情id
     * @param classInfoId       班级id
     * @param noMoneyStudentIds 没有钱的学生id集合
     * @param allStudentIds     班级下所有学生id集合
     * @author WangCX
     * @since 2022/8/2 15:56
     */
    @Transactional(rollbackFor = Exception.class)
    public void cannotOpenClass(String scheduleDetailId, String classInfoId, String noMoneyStudentIds, String allStudentIds) {

        List<String> noMoneyStuIds = Arrays.asList(noMoneyStudentIds.split(","));
        List<String> allStuIds = Arrays.asList(allStudentIds.split(","));
        // 获取没钱学员姓名
        List<String> noMoneyStuIdNames = this.studentMapper.selectList(new LambdaQueryWrapper<Student>().in(Student::getId, noMoneyStuIds))
                .stream().map(Student::getStudentName).collect(Collectors.toList());
        String noMoneyStuIdName = StringUtils.join(noMoneyStuIdNames, "、");
        // 获取家长的WxUser集合
        List<WxUser> wxUsers = this.userStudentRelMapper.getWxUserByStuId(allStuIds);
        // 根据班级id获取班级实体
        ClassInfo classInfo = classInfoMapper.selectById(classInfoId);
        // 获取教练coachWxUser
        WxUser coachWxUser = this.wxUserMapper.getWxUserByCoachId(classInfo.getCoachId());
        // 根据课表id获取开始和结束时间 和日期
        CourseScheduleDetail courseScheduleDetail = courseScheduleDetailMapper.selectById(scheduleDetailId);
        // 课程名称
        String courseName = this.courseMapper.selectById(classInfo.getCourseId()).getCourseName();
        // 获取团长WxUser实体类
        WxUser tourLeaderWxUser = this.wxUserMapper.selectOne(new LambdaQueryWrapper<WxUser>().eq(WxUser::getId, classInfo.getWxUserId()));
        // 时间
        String time = new SimpleDateFormat("yyyy-MM-dd").format(courseScheduleDetail.getCourseDate()) + " "
                + new SimpleDateFormat("HH:mm").format(courseScheduleDetail.getStartTime())
                + "-" + new SimpleDateFormat("HH:mm").format(courseScheduleDetail.getEndTime());

        String content = "因人数不足，本节课无法开课! " + "课程名称：" + courseName + " 时间：" + time;
        // 微信通用消息模板
        List<WxMaTemplateData> dataList = new ArrayList<>();
        dataList.add(new WxMaTemplateData("first", "因人数不足，本节课无法开课!"));
        dataList.add(new WxMaTemplateData("keyword1", courseName));
        dataList.add(new WxMaTemplateData("keyword2", time));


        // 存入消息表和消息通知表
        Message message = new Message();
        message.setContent(content);
        message.setMsgType(MessageTypeEnum.NO_ENOUGH_MONEY.getValue());
        message.setTitle(MessageTypeEnum.NO_ENOUGH_MONEY.getValue());
        message.setReceiverType(MessageTypeEnum.RECEIVER_TYPE_OTHER.getValue());
        this.messageMapper.insert(message);
        MessageNotify notify = new MessageNotify();
        notify.setMessageId(message.getId());
        notify.setSendTime(new Date());

        // 通知团长
        if (ParamUtils.isNotEmpty(tourLeaderWxUser) && !wxUsers.contains(tourLeaderWxUser)) {
            // 公众号消息推送
            if (ParamUtils.isNotEmpty(tourLeaderWxUser) && ParamUtils.isNotEmpty(tourLeaderWxUser.getOpenId())) {
                publicPush(dataList, null, tourLeaderWxUser,
                        properties.getWx().getMessageTemplate().getCourseRemind(), content);
                log.info("消息通知-班级无法开课：团长 " + content);
            }
        }

        // 通知家长
        if (ParamUtils.isNotEmpty(wxUsers)) {
            for (WxUser wxUser : wxUsers) {
                // 公众号消息推送
                if (ParamUtils.isNotEmpty(wxUser) && ParamUtils.isNotEmpty(wxUser.getOpenId())) {
                    publicPush(dataList, null, wxUser, properties.getWx().getMessageTemplate().getCourseRemind(),
                            content);
                    log.info("消息通知-班级无法开课：家长 " + content);
                }
            }
        }
        // 给教练发送消息
        List<WxMaTemplateData> dataList2 = new ArrayList<>();
        dataList2.add(new WxMaTemplateData("first", "因人数不足，本节课无法开课!"));
        dataList2.add(new WxMaTemplateData("keyword1", courseName));
        dataList2.add(new WxMaTemplateData("keyword2", time));
        dataList2.add(new WxMaTemplateData("remark", "学员：" + noMoneyStuIdName));

        // 公众号消息推送
        if (ParamUtils.isNotEmpty(coachWxUser) && ParamUtils.isNotEmpty(coachWxUser.getOpenId())) {
            publicPush(dataList2, null, coachWxUser, properties.getWx().getMessageTemplate().getCourseRemind(),
                    content);
            log.info("消息通知-班级无法开课：教练 " + content + "学员：" + noMoneyStuIdNames);
        }
        this.save(notify);

    }

    /**
     * function: 人数不足，拼班失败
     *
     * @param classInfoId 班级id
     * @author WangCX
     * @since 2022/8/9 17:31
     */
    @Transactional(rollbackFor = Exception.class)
    public void noEnoughPeople(String classInfoId) {
        // 根据班级id获取班级实体
        ClassInfo classInfo = classInfoMapper.selectById(classInfoId);
        // 课程名称
        String courseName = this.courseMapper.selectById(classInfo.getCourseId()).getCourseName();
        // 时间转化格式
        String time = new SimpleDateFormat("yyyy-MM-dd HH:mm").format(new Date());
        // 获取团长WxUser实体类
        WxUser tourLeaderWxUser = this.wxUserMapper.selectOne(new LambdaQueryWrapper<WxUser>().eq(WxUser::getId, classInfo.getWxUserId()));
        // 根据班级id获取家长的wxUser集合
        List<WxUser> parentWxUsers = this.classInfoMapper.getParentWxUsers(classInfoId);
        // 消息内容
        String content = "因人数不足，拼班失败!" + "课程名称：" + courseName + "时间：" + time;

        // 存入消息表和消息通知表
        Message message = new Message();
        message.setContent(content);
        message.setMsgType(MessageTypeEnum.NO_ENOUGH_PEOPLE.getValue());
        message.setTitle(MessageTypeEnum.NO_ENOUGH_PEOPLE.getValue());
        message.setReceiverType(MessageTypeEnum.RECEIVER_TYPE_OTHER.getValue());
        this.messageMapper.insert(message);
        MessageNotify notify = new MessageNotify();
        notify.setMessageId(message.getId());
        notify.setSendTime(new Date());

        // 通知家长
        // 微信通用消息模板
        List<WxMaTemplateData> dataList = new ArrayList<>();
        dataList.add(new WxMaTemplateData("first", "您参与的拼班因人数不足，拼班失败!"));
        dataList.add(new WxMaTemplateData("keyword1", courseName));
        dataList.add(new WxMaTemplateData("keyword2", time));
        // 通知家长
        if (ParamUtils.isNotEmpty(parentWxUsers)) {
            for (WxUser wxUser : parentWxUsers) {
                // 公众号消息推送
                if (ParamUtils.isNotEmpty(wxUser.getOpenId()) && !tourLeaderWxUser.equals(wxUser)) {
                    publicPush(dataList, null, wxUser,
                            properties.getWx().getMessageTemplate().getNoEnoughPeople(), content);
                }
            }
        }
        // 通知团长
        List<WxMaTemplateData> dataList2 = new ArrayList<>();
        dataList2.add(new WxMaTemplateData("first", "您发起的拼班因人数不足，拼班失败!"));
        dataList2.add(new WxMaTemplateData("keyword1", courseName));
        dataList2.add(new WxMaTemplateData("keyword2", time));
        if (ParamUtils.isNotEmpty(tourLeaderWxUser)) {
            // 公众号消息推送
            publicPush(dataList2, null, tourLeaderWxUser,
                    properties.getWx().getMessageTemplate().getNoEnoughPeople(), content);
        }

        this.save(notify);
        log.info("消息通知-拼班失败提醒：" + content);

    }


    /**
     * 班级解散（到期结课）提醒
     * 班级解散（团长解散）提醒
     * 班级解散 （人数不足）提醒
     *
     * @param classInfoId     班级id
     * @param messageTypeEnum 班级解散消息通知类型
     * @author wangcx
     * @since 2022/7/20 9:51
     */
    @Transactional(rollbackFor = Exception.class)
    public void classDissolvedDueDate(String classInfoId, MessageTypeEnum messageTypeEnum) {
        String content = null;
        List<WxMaTemplateData> dataList = new ArrayList<>();
        // 根据班级id获取班级实体
        ClassInfo classInfo = classInfoMapper.selectById(classInfoId);
        // 获取机构负责人Id
        String orgStaffId = getOrgStaffIdByOrgId(classInfo.getOrganizationId());
        // 获取教练WxUser
        WxUser wxUserCoach = coachMapper.getWxUserByCoachId(classInfo.getCoachId());
        // 根据班级id获取家长的wxUser集合
        List<WxUser> parentWxUsers = this.classInfoMapper.getParentWxUsers(classInfoId);
        // 时间转化格式
        String time = new SimpleDateFormat("yyyy-MM-dd").format(new Date());
        // 获取团长WxUser实体类
        WxUser tourLeaderWxUser = this.wxUserMapper.selectOne(new LambdaQueryWrapper<WxUser>().eq(WxUser::getId, classInfo.getWxUserId()));
        if (messageTypeEnum.equals(MessageTypeEnum.CLASS_DISSOLVED_DUE_DATE)) {
            // 消息内容
            content = classInfo.getClassName() + "，于" + time + "完成所有授课内容，班级自动解散。";
            // 微信通用消息模板
            dataList.add(new WxMaTemplateData("first", messageTypeEnum.getDesc()));
            dataList.add(new WxMaTemplateData("keyword1", "班级自动解散"));
            dataList.add(new WxMaTemplateData("keyword2", time));
            dataList.add(new WxMaTemplateData("remark", "您所在" + classInfo.getClassName() + "班级完成所有授课内容，已自动解散"));
        } else if (messageTypeEnum.equals(MessageTypeEnum.CLASS_DISSOLVED_GIRTH)) {
            // 获取团长的姓名和电话
            WxUser wxUser = this.wxUserMapper.selectOne(new LambdaQueryWrapper<WxUser>().eq(WxUser::getId, classInfo.getWxUserId()));
            if (ParamUtils.isEmpty(wxUser.getName())) {
                wxUser.setName("匿名");
            }
            // 消息内容
            content = classInfo.getClassName() + ",团长（" + wxUser.getName() + "," + wxUser.getPhone() + "）于" + time + "解散班级。";
            // 微信通用消息模板
            dataList.add(new WxMaTemplateData("first", MessageTypeEnum.CLASS_DISSOLVED_GIRTH.getDesc()));
            dataList.add(new WxMaTemplateData("keyword1", "团长（" + wxUser.getName() + "," + wxUser.getPhone() + ")"));
            dataList.add(new WxMaTemplateData("keyword2", time));
            dataList.add(new WxMaTemplateData("remark", "您所在的" + classInfo.getClassName() + "已被团长解散"));
        } else if (messageTypeEnum.equals(MessageTypeEnum.CLASS_DISSOLVED_NO_ENOUGH)) {
            // 消息内容
            content = classInfo.getClassName() + "，连续3次不满开班最低人数要求，班级已自动解散";
            // 微信通用消息模板
            dataList.add(new WxMaTemplateData("first", MessageTypeEnum.CLASS_DISSOLVED_NO_ENOUGH.getDesc()));
            dataList.add(new WxMaTemplateData("keyword1", "班级自动解散"));
            dataList.add(new WxMaTemplateData("keyword2", time));
            dataList.add(new WxMaTemplateData("remark", "您所在的" + classInfo.getClassName()
                    + "连续" + this.getConfigValue(SysConfigTypeEnum.B) + "次不满开班最低人数要求，班级已自动解散"));
        } else {
            return;
        }
        // 存入消息表和消息通知表
        Message message = new Message();
        message.setContent(content);
        message.setMsgType(messageTypeEnum.getValue());
        message.setTitle(messageTypeEnum.getDesc());
        message.setReceiverType(MessageTypeEnum.RECEIVER_TYPE_ORG.getValue());
        this.messageMapper.insert(message);
        MessageNotify notify = new MessageNotify();
        notify.setMessageId(message.getId());
        notify.setSendTime(new Date());

        // 通知团长
        if (!parentWxUsers.contains(tourLeaderWxUser)) {
            // 公众号消息推送
            if (ParamUtils.isNotEmpty(tourLeaderWxUser) && ParamUtils.isNotEmpty(tourLeaderWxUser.getOpenId())) {
                publicPush(dataList, null, tourLeaderWxUser,
                        properties.getWx().getMessageTemplate().getCourseDissolved(), content);
            }
        }


        // 通知家长
        if (ParamUtils.isNotEmpty(parentWxUsers)) {
            for (WxUser parentWxUser : parentWxUsers) {
                // 公众号消息推送
                if (ParamUtils.isNotEmpty(parentWxUser.getOpenId())) {
                    publicPush(dataList, null, parentWxUser,
                            properties.getWx().getMessageTemplate().getCourseDissolved(), content);
                }
            }
        }

        // 给教练发送消息
        // 公众号消息推送
        if (!parentWxUsers.contains(wxUserCoach)) {
            if (ParamUtils.isNotEmpty(wxUserCoach) && ParamUtils.isNotEmpty(wxUserCoach.getOpenId())) {
                publicPush(dataList, null, wxUserCoach,
                        properties.getWx().getMessageTemplate().getCourseDissolved(), content);

                notify.setOrganizationStaffId(orgStaffId);
                this.save(notify);
            }
        }
        log.info("消息通知-班级解散：" + content + "\n班级id:" + classInfoId);
    }


    /**
     * function：根据机构id获取机构负责人Id
     *
     * @param organizationId 机构id
     * @return organizationStaffId 机构负责人id
     * @author wangcx
     * @since 2022/7/25 9:48
     */
    private String getOrgStaffIdByOrgId(String organizationId) {
        OrganizationStaff organizationStaff = this.organizationStaffMapper.selectOne(new LambdaQueryWrapper<OrganizationStaff>()
                .eq(OrganizationStaff::getDeleted, false).eq(OrganizationStaff::getOrganizationId, organizationId)
                .eq(OrganizationStaff::getIsPrincipal, true));
        return ParamUtils.isNotEmpty(organizationStaff)?organizationStaff.getId():null;
    }

    /**
     * function：根据学生id获取用户
     *
     * @param studentId 学生id
     * @return WxUser   WxUser实体类
     * @author wangcx
     * @since 2022/7/25 9:52
     */
    public WxUser getWxUserByStuId(String studentId) {
        UserStudentRel userStudentRel = this.userStudentRelMapper.selectOne(new LambdaQueryWrapper<UserStudentRel>()
                .eq(UserStudentRel::getDeleted, false)
                .eq(UserStudentRel::getStudentId, studentId));
        return this.wxUserMapper.selectById(userStudentRel.getUserId());
    }


    /**
     * function：根据通知类型获取阈值
     *
     * @param sysConfigTypeEnum 系统配置项
     * @return Integer          还有几个小时
     * @author wangcx
     * @since 2022/7/22 9:45
     */
    public Integer getConfigValue(SysConfigTypeEnum sysConfigTypeEnum) {
        Config config = this.configMapper.selectOne(new LambdaQueryWrapper<Config>()
                .eq(Config::getType, sysConfigTypeEnum.getValue()));
        return ParamUtils.isNotEmpty(config)?Integer.parseInt(config.getValue()):1;
    }

    /**
     * function：跳转小程序推送消息方法
     *
     * @param dataList   微信推送的消息内容
     * @param page       跳转页面
     * @param wxUser     推送人
     * @param templateId 模板id
     * @param content    存到数据库的消息内容
     * @author wangcx
     * @since 2022/7/21 9:40
     */
    public void publicPush(List<WxMaTemplateData> dataList, String page, WxUser wxUser, String templateId,
                           String content) {

        WxMaMsgService msgService = wxMaService.getMsgService();
        WxMaUniformMessage.MiniProgram miniProgram = new WxMaUniformMessage.MiniProgram();
        miniProgram.setAppid(properties.getWx().getMiniapp().getAppid());
        // 跳转
        miniProgram.setPagePath(page);
        WxMaUniformMessage wxMaUniformMessage = WxMaUniformMessage.builder()
                .appid(properties.getWx().getMiniapp().getMpAppid())
                .isMpTemplateMsg(true)
                .toUser(wxUser.getOpenId())
//TODO:小程序上线后解封      .miniProgram(miniProgram)
                .templateId(templateId)
                .data(dataList)
                .build();
        // 保存到微信通知日志表
        WxMessageLog messageLog = new WxMessageLog();
        messageLog.setContent(content);
        messageLog.setTemplateId(templateId);
        messageLog.setPagePath(page);
        messageLog.setWxUserId(wxUser.getId());
        wxMessageLogMapper.insert(messageLog);
        CompletableFuture.runAsync(() -> {
            try {
                msgService.sendUniformMsg(wxMaUniformMessage);
            } catch (WxErrorException e) {
                log.error("公众号提醒推送失败，openId：" + wxUser.getOpenId());
                e.printStackTrace();
            }
        });

    }


}

